package model;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import lucene.PaperSearcher;

import data.TestUserSelection;
import data.TrainTestPaperRetrieval;

public class AuthorBayesianPredictor {
	private String user;
	private HashSet<String> holdoutPapers = new HashSet<String>();
	private HashSet<String> usedTags = new HashSet<String>();
	private HashMap<String, Double> tagProbMap = new HashMap<String, Double>();
	private HashMap<String, Double> tagAuthorMap = new HashMap<String, Double>();
	private PaperSearcher generalSearcher;

	public AuthorBayesianPredictor(String user, PaperSearcher gSearcher) throws Exception {
		this.user = user;
		this.generalSearcher = gSearcher;
		this.holdoutPapers = TrainTestPaperRetrieval.retrieveTest(user);
		loadTagProbMap();

		//this.trainPapers = TrainTestPaperRetrieval.retrieveTrain(user);
		loadTagAuthorMap();
		System.out.println("tagAuthorMap size\t"
				+ tagAuthorMap.entrySet().size());
	}

	private void loadTagAuthorMap() throws Exception {
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\tag_author_map.txt";
		BufferedReader reader = new BufferedReader(new FileReader(path));
		String line = null;
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			String[] tokens = line.split("\t");
			String tag = tokens[0];
			String term = tokens[1];
			double s = Double.valueOf(tokens[2]);
			tagAuthorMap.put(tag + "\t" + term, s);
		}

	}

	private void loadTagProbMap() throws Exception {
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\tagProb.txt";
		BufferedReader reader = new BufferedReader(new FileReader(path));
		String line = null;
		while ((line = reader.readLine()) != null) {
			line = line.trim();
			String[] tokens = line.split("\t");
			String tag = tokens[0];
			usedTags.add(tag);
			double s = Double.valueOf(tokens[1]);
			tagProbMap.put(tag, s);
		}

	}

	public void predict() throws Exception {
		String path = "D:\\CityU\\project\\bibsonomy\\experiment\\" + user
				+ "\\result\\author\\";
		File dir = new File(path);
		if (!dir.exists()) {
			dir.mkdirs();
		}

		for (String testCase : holdoutPapers) {
			String testCasePath = path + testCase + ".txt";
			//int docId = generalSearcher.retrieveDocByPid(testCase);
			HashSet<String> authors = generalSearcher
					.retrieveAuthorsByPid(testCase);
            writeAuthorResult(authors,testCasePath);
		}

	}

	private void writeAuthorResult(HashSet<String> authors, String testCasePath)
			throws Exception {
		BufferedWriter writer = new BufferedWriter(new FileWriter(testCasePath));
		List<RelevantNode> results = new ArrayList<RelevantNode>();
		try {
			for (String usedTag : usedTags) {
				double usedTagProb = tagProbMap.get(usedTag);
				double prob = 0.0;
				for (String author : authors) {
					Double authorTagProb = tagAuthorMap.get(usedTag + "\t"
							+ author);
					if (authorTagProb == null) {
						authorTagProb = 0.0;
					}
					authorTagProb = Math.log1p(authorTagProb) / Math.log(2);
					prob = prob + authorTagProb;
				}
				prob = prob / authors.size();
				Double score = (Math.log1p(usedTagProb) / Math.log(2)) + prob;

				if (score.isNaN()) {
					System.err.println("err\t" + testCasePath + "\tisNaN");
				}
				RelevantNode node = new RelevantNode(usedTag, score);
				results.add(node);
			}
			Collections.sort(results);
			for (RelevantNode rn : results) {
				String t = rn.getPid();
				double v = rn.getScore();
				writer.write(t + "\t" + v);
				writer.newLine();
			}

		} finally {
			writer.flush();
			writer.close();
		}

	}

	public static void main(String[] args) throws Exception{
	List<String> users = TestUserSelection.retrieveTestUsers();
		
		File indexDir = new File("D:\\CityU\\project\\bibsonomy\\"
				+ "\\BibIndex\\");
		PaperSearcher gSearcher = new PaperSearcher(indexDir);
		
		for(String user : users) {
			AuthorBayesianPredictor app = new AuthorBayesianPredictor(user,gSearcher);
			System.out.println("run test user\t" + user);
			app.predict();
		}
		
	}
	
	
}
